package com.pan.admin.generator.util;

import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.base.Eq;
import com.gitee.apanlh.util.base.IteratorUtils;
import com.gitee.apanlh.util.base.StringUtils;
import com.gitee.apanlh.util.valid.ValidParam;
import com.pan.admin.cache.FormLocalCache;
import com.pan.admin.generator.constant.ApiGenFieldEnum;
import com.pan.admin.generator.constant.ApiGenPlatParseDataExchangeFieldEnum;
import com.pan.admin.generator.entity.ApiGenField;
import com.pan.admin.generator.entity.ApiGenFormField;
import com.pan.admin.generator.entity.ApiGenResponseField;

import java.util.List;

/**
 *  API对接生成工具类
 *
 *  @author Pan
 */
public class ApiGenUtils {

    /**
     *  过滤无用数据
     *
     *  @param  listApiGenField
     */
    public static void filterNone(List<ApiGenField> listApiGenField, boolean hasFormFilter) {
        //  过滤掉字段名和映射字段名都为空的属性
        CollUtils.filter(listApiGenField, t -> ValidParam.isEmpty(t.getFieldName()));
        CollUtils.filter(listApiGenField, t -> ValidParam.isEmpty(t.getMappingName()));

        //  忽略表单资质为空的数据
        if (hasFormFilter) {
            CollUtils.filter(listApiGenField, t -> ValidParam.isEmpty(t.getListFormField()));
        }
    }

    /**
     *  生成字段实体类文本
     *
     *  @param  listApiGenField     需要转换的字段
     *  @param  hasJsonField        是否增加JSONField转换
     *  @return String
     */
    public static String generateFieldEntityText(List<ApiGenField> listApiGenField, boolean hasJsonField) {
        filterNone(listApiGenField, false);
        if (ValidParam.isEmpty(listApiGenField)) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        //  实体类
        for (int i = 0; i < listApiGenField.size(); i++) {
            ApiGenField apiGenField = listApiGenField.get(i);
            //  注释
            if (ValidParam.isNotEmpty(apiGenField.getFieldDoc())) {
                sb.append("\t").append("/** ").append(apiGenField.getFieldDoc()).append(" */");
            }
            //  属性转换
            if (hasJsonField) {
                sb.append("\n\t").append("@JSONField(name = ").append("\"").append(apiGenField.getMappingName()).append("\")");
            }
            //  私有方法
            sb.append("\n\t").append("private ");
            //  类型
            sb.append(apiGenField.getJavaType()).append(" ");
            //  属性名
            sb.append(apiGenField.getFieldName());
            //  映射值
            if (ValidParam.isNotEmpty(apiGenField.getMappingValue())) {
                sb.append(" = ");

                String mappingValue = apiGenField.getMappingValue();
                String javaType = apiGenField.getJavaType();

                //  类型判断
                String appendValue = getValueByJavaType(mappingValue, javaType);
                sb.append(appendValue);
            }
            sb.append(";");

            //  第一次添加默认换行
            if (i == 0) {
                sb.append("\r\n");
            }
        }
        return sb.toString();
    }

    /**
     *  生成赋值表单字段模板
     *
     *  @param  listApiGenField 需要转换的字段
     *  @param  entityName      实体类名称
     *  @param  messageName     传递消息名称
     *  @return String
     */
    public static String generateSetFieldText(List<ApiGenField> listApiGenField, String entityName, String messageName) {
        filterNone(listApiGenField, false);
        if (ValidParam.isEmpty(listApiGenField)) {
            return "";
        }

        //  如果存在表单项则都过滤不生成
        List<ApiGenField> copyListApiGenField = CollUtils.copy(listApiGenField);
        CollUtils.filter(copyListApiGenField, t -> ValidParam.isNotEmpty(FormLocalCache.getByMappingName(t.getFieldName())));

        if (ValidParam.isEmpty(copyListApiGenField)) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < copyListApiGenField.size(); i++) {
            ApiGenField apiGenField = copyListApiGenField.get(i);
            String fieldName = apiGenField.getFieldName();
            String upperFirstFieldName = StringUtils.upperFirst(fieldName);

            //  添加赋值语句
            sb.append("        ").append(entityName).append(".set").append(upperFirstFieldName);
            sb.append("(").append(messageName).append(".get").append(upperFirstFieldName).append("()").append(");\n");
        }
        return sb.toString();
    }

    /**
     *  生成赋值表单字段模板
     *
     *  @param  listApiGenField 需要转换的字段
     *  @param  messageName     需要赋值的实体名称
     *  @param  messageName     传递消息名称
     *  @return String
     */
    public static String generateSetFormFieldText(List<ApiGenField> listApiGenField, String entityName, String messageName) {
        filterNone(listApiGenField, true);
        if (ValidParam.isEmpty(listApiGenField)) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        //  变量 + 字段名 + message名称 + 首字母大写字段名 + 换行
        String variablesFormat = "        {variables} {fieldName} = ChooseEq.create({message}.get{upperFieldName}())\n";

        //  主字段
        for (int i = 0; i < listApiGenField.size(); i++) {
            ApiGenField apiGenField = listApiGenField.get(i);
            //  获取字段中表单映射字段
            List<ApiGenFormField> listFormField = apiGenField.getListFormField();

            //  非首次添加则默认开头添加换行符
            if (i != 0) {
                sb.append("\n");
            }

            //  添加文档
            ApiGenFieldEnum apiGenFieldEnum = ApiGenFieldEnum.getByFieldName(apiGenField.getFieldName());
            String genDoc = apiGenFieldEnum.getGenDoc();
            sb.append(genDoc);

            //  添加首行文本
            String javaType = apiGenField.getJavaType();
            String fieldName = apiGenField.getFieldName();
            String upperFirstFieldName = StringUtils.upperFirst(fieldName);
            String firstLine = StringUtils.replaceByOrder(variablesFormat, "{", "}",
                javaType,
                fieldName,
                messageName,
                upperFirstFieldName
            );
            sb.append(firstLine);

            //  获取模板文字
            for (int j = 0; j < listFormField.size(); j++) {
                ApiGenFormField apiGenFormField = listFormField.get(j);
                String fieldValue = apiGenFormField.getFieldValue();
                String mappingValue = apiGenFormField.getMappingValue();

                //  将所有字段名称去除中文化
                if (fieldValue.indexOf('-') != -1) {
                    fieldValue = StringUtils.split(fieldValue, "-")[0];
                }

                //  添加if语句
                sb.append("            ").append(".when(").append("\"").append(fieldValue).append("\",");
                sb.append(" ");

                //  类型判断
                String appendValue = getValueByJavaType(mappingValue, javaType);
                sb.append(appendValue);

                sb.append(")");
                sb.append("\n");
            }

            //  添加if结束语句
            sb.append("        ").append(".end();").append("\n");

            //  赋值语句
            sb.append("        ").append(entityName).append(".set").append(upperFirstFieldName).append("(").append(fieldName).append(");");
            sb.append("\n");
        }
        return sb.toString();
    }

    /**
     *  生成响应字段文本
     *
     *  @param  apiGenResponseField  响应实体类
     *  @return String
     */
    public static String generateResponseFieldText(ApiGenResponseField apiGenResponseField) {
        if (ValidParam.isNull(apiGenResponseField)) {
            return "";
        }

        String key = apiGenResponseField.getKey();
        String code = apiGenResponseField.getCode();
        String javaType = apiGenResponseField.getJavaType();

        //  剔除没有键以及没有code的实体
        if (ValidParam.isEmpty(key) || ValidParam.isEmpty(code)) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        //  响应判断赋值
        sb.append("        ").append("return Eq.object(jsonObject.get");
        sb.append(javaType).append("(").append("\"").append(key).append("\")").append(", ");

        //  类型判断
        String value = getValueByJavaType(code, javaType);
        sb.append(value).append(");");
        return sb.toString();
    }

    /**
     *  生成解析响应撞库模板
     *
     *  @param  listGenParseDataExchangeField
     *  @return String
     */
    public static String generateParseDataExchangeText(List<ApiGenField> listGenParseDataExchangeField) {
        filterNone(listGenParseDataExchangeField, false);

        if (ValidParam.isEmpty(listGenParseDataExchangeField)) {
            return "";
        }

        StringBuilder sb = new StringBuilder();

        //  响应体数据
        ApiGenField data = CollUtils.findOne(listGenParseDataExchangeField, t -> t.getFieldName().equals("data"));
        if (ValidParam.isNull(data)) {
            throw new NullPointerException("解析响应撞库-丢失响应体数据");
        }

        //  制表符
        String tab = "        ";
        //  响应体
        String respBodyText = tab + "JSONObject respBody = JsonUtils.get(respJson);";
        //  data文本
        String dataText = tab + "JSONObject resData = JsonUtils.get(respJson).getJSONObject(\"{mappingName}\");";
        //  外层数据文本
        String outerDataFormatText = tab + "{fieldName} = respBody.get{javaType}(\"{mappingName}\");";
        //  内层数据文本
        String innerDataFormatText = tab + "{fieldName} = resData.get{javaType}(\"{mappingName}\");";
        //  协议文本
        String protocolFormatText = tab + "JSONArray {fieldName} = resData.getJSONArray(\"{mappingName}\");";
        String protocolForText = """
            if (ValidParam.isNotEmpty({protocolListMappingName})) {
                protocolList = CollUtils.newArrayList();
                for (int i = 0; i < {protocolListMappingName}.size(); i++) {
                    JSONObject protocolJsonObject = {protocolListMappingName}.getJSONObject(i);
                    String protocolName = protocolJsonObject.getString("{protocolName}");
                    String protocolUrl = protocolJsonObject.getString("{protocolUrl}");
                    
                    ApiPlatFormProtocolDataExchange protocol = new ApiPlatFormProtocolDataExchange();
                    protocol.setProtocolName(protocolName);
                    protocol.setProtocolUrl(protocolUrl);
                    protocolList.add(protocol);
                }
            }
    """;

        String listPhoneMd5ForText = """
            //  获取手机号掩码
            JSONArray md5JsonArray = resData.getJSONArray("{mappingName}");
            if (ValidParam.isNotEmpty(md5JsonArray)) {
                listPhoneMd5 = CollUtils.newArrayList();
                for (int i = 0; i < md5JsonArray.size(); i++) {
                    String phoneMd5 = md5JsonArray.getString(i);
                    listPhoneMd5.add(phoneMd5);
                }
            }
    """;

        //  添加获取响应体
        sb.append(respBodyText).append("\n").append("\n");

        //  获取值
        sb.append(tab).append("//  获取属性值").append("\n");
        IteratorUtils.array(listGenParseDataExchangeField, apiGenField -> {
            String fieldName = apiGenField.getFieldName();
            String mappingName = apiGenField.getMappingName();
            String javaType = apiGenField.getJavaType();

            //  data处理
            if (Eq.str(ApiGenPlatParseDataExchangeFieldEnum.DATA.getFieldName(), fieldName)) {
                sb.append(StringUtils.replaceByOrder(dataText, "{", "}",mappingName)).append("\n");
                return ;
            }

            //  code/msg处理
            if (Eq.strOr(fieldName, ApiGenPlatParseDataExchangeFieldEnum.CODE.getFieldName(),
                    ApiGenPlatParseDataExchangeFieldEnum.MSG.getFieldName())) {

                String replace = StringUtils.replaceByOrder(outerDataFormatText, "{", "}", fieldName, javaType, mappingName);
                sb.append(replace).append("\n");
                return ;
            }

            //  协议处理
            if (Eq.str(ApiGenPlatParseDataExchangeFieldEnum.PROTOCOL_LIST.getFieldName(), fieldName)) {
                //  获取协议对象
                sb.append("\n").append(tab).append("//  获取协议内容");
                String replaceProtocolFormatText = StringUtils.replaceByOrder(protocolFormatText, "{", "}", fieldName, mappingName);
                sb.append("\n");
                sb.append(replaceProtocolFormatText).append("\n");

                //  获取协议名称
                ApiGenField protocolName = CollUtils.findOne(listGenParseDataExchangeField, t -> Eq.str(ApiGenPlatParseDataExchangeFieldEnum.PROTOCOL_NAME.getFieldName(), t.getFieldName()));
                //  获取协议url
                ApiGenField protocolUrl = CollUtils.findOne(listGenParseDataExchangeField, t -> Eq.str(ApiGenPlatParseDataExchangeFieldEnum.PROTOCOL_NAME_URL.getFieldName(), t.getFieldName()));

                String finalText;
                finalText = StringUtils.replace(protocolForText,"{protocolListMappingName}", mappingName);
                finalText = StringUtils.replace(finalText,"{protocolName}", protocolName.getMappingName());
                finalText = StringUtils.replace(finalText,"{protocolUrl}", protocolUrl.getMappingName());
                sb.append(finalText);
                return ;
            }

            //  手机号掩码模式处理
            if (Eq.str(ApiGenPlatParseDataExchangeFieldEnum.LIST_PHONE_MD5.getFieldName(), fieldName)) {
                String listPhoneMd5Text = StringUtils.replace(listPhoneMd5ForText,"{mappingName}", mappingName);
                sb.append("\n").append(listPhoneMd5Text);
                return ;
            }

            //  忽略协议名字以及协议名称
            if (Eq.strOr(fieldName, ApiGenPlatParseDataExchangeFieldEnum.PROTOCOL_NAME.getFieldName(),
                    ApiGenPlatParseDataExchangeFieldEnum.PROTOCOL_NAME_URL.getFieldName())) {
                return ;
            }
            //  内部文本处理
            sb.append(StringUtils.replaceByOrder(innerDataFormatText, "{", "}", fieldName, javaType, mappingName)).append("\n");
        });

        //  返回值处理-空值忽略
        String resultText = "ApiPlatFormDataExchange result = new ApiPlatFormDataExchange();";
        sb.append("\n").append(tab).append("//  返回转换内容");
        sb.append("\n").append(tab).append(resultText).append("\n");
        IteratorUtils.array(listGenParseDataExchangeField, apiGenField -> {
            //  忽略data
            if (Eq.str(ApiGenPlatParseDataExchangeFieldEnum.DATA.getFieldName(), apiGenField.getFieldName())) {
                return ;
            }

            String fieldName = apiGenField.getFieldName();
            String resultFieldName = "result.set{upperFirstFieldName}({fieldName});";
            String replaceText = StringUtils.replaceByOrder(resultFieldName, "{", "}", StringUtils.upperFirst(fieldName), fieldName);
            sb.append(tab).append(replaceText).append("\n");
        });
        return sb.toString();
    }

    /**
     *  生成解析拉取进件通知模板
     *
     *  @param  listGenApplyPullField   拉取进件通知实体
     *  @return String
     */
    public static String generateApplyPullFieldText(List<ApiGenField> listGenApplyPullField) {
        filterNone(listGenApplyPullField, false);
        if (ValidParam.isEmpty(listGenApplyPullField)) {
            return "";
        }

        //  关联文本
        String tab = "        ";
        String getFormatText = "{javaType} {fieldName} = jsonObject.get{javaType}(\"{mappingName}\");";
        String setNoticeText = "ApiPlatFormApplyNoticeMessage applyNotice = new ApiPlatFormApplyNoticeMessage();";
        String setFormatText = "applyNotice.set{upperFieldName}({fieldName});";

        StringBuilder sb = new StringBuilder();

        //  获取值
        IteratorUtils.array(listGenApplyPullField, apiGenField -> {
            String javaType = apiGenField.getJavaType();
            String fieldName = apiGenField.getFieldName();
            String mappingName = apiGenField.getMappingName();

            //  替换文本
            String replaceText = StringUtils.replaceByOrder(getFormatText, "{", "}",
                javaType,
                fieldName,
                javaType,
                mappingName
            );

            sb.append(tab).append(replaceText).append("\n");
        });

        //  设置值
        sb.append("\n").append(tab).append(setNoticeText).append("\n");
        IteratorUtils.array(listGenApplyPullField, apiGenField -> {
            String fieldName = apiGenField.getFieldName();
            String upperFieldName = StringUtils.upperFirst(fieldName);

            //  替换文本
            String replaceText = StringUtils.replaceByOrder(setFormatText, "{", "}",
                upperFieldName,
                fieldName
            );
            sb.append(tab).append(replaceText).append("\n");
        });
        sb.append(tab).append("return applyNotice;");
        return sb.toString();
    }

    /**
     /**
     *  生成解析拉取进件通知模板
     *
     *  @param  applyPullSucResponse        成功码实体
     *  @param  applyPullSucMsgResponse     成功消息实体
     *  @param  applyPullFailResponse       失败消息实体
     *  @return String
     */
    public static String generateApplyPullResponseText(ApiGenResponseField applyPullSucResponse, ApiGenResponseField applyPullSucMsgResponse, ApiGenResponseField applyPullFailResponse) {
        if (!ValidParam.requiredBean(applyPullSucMsgResponse) || !ValidParam.requiredBean(applyPullFailResponse) || !ValidParam.requiredBean(applyPullSucResponse)) {
            return "";
        }

        String formatText = """
            boolean hasBizSuc = apiBizStatus.hasBizSuc();
            //  成功响应
            if (hasBizSuc) {
                return MapUtils.newHashMap(newHashMap -> {
                    newHashMap.put("${codeKey}", ${codeSucValue});
                    newHashMap.put("${msgKey}", "${msgSucValue}");
                });
            }
            //  失败响应
            return MapUtils.newHashMap(newHashMap -> {
                newHashMap.put("${codeKey}", ${codeFailValue});
                newHashMap.put("${msgKey}", apiBizStatus.getBizMsg());
            });
    """;

        //  成功响应码
        String codeKey = applyPullSucResponse.getKey();
        String sucCodeValue = applyPullSucResponse.getCode();
        String sucCodeJavaType = applyPullSucResponse.getJavaType();
        //  失败响应码
        String failCodeValue = applyPullFailResponse.getCode();

        //  成功响应消息
        String msgKey = applyPullSucMsgResponse.getKey();
        String msgValue = applyPullSucMsgResponse.getCode();

        //  替换文本
        String replaceText = StringUtils.replaceByOrder(formatText, "${", "}",
            codeKey, getValueByJavaType(sucCodeValue, sucCodeJavaType),
            msgKey, msgValue,
            codeKey, getValueByJavaType(failCodeValue, sucCodeJavaType),
            msgKey
        );
        return replaceText;
    }

    /**
     *  根据java类型获取值
     *
     *  @return String
     */
    private static String getValueByJavaType(String value, String javaType) {
        //  类型判断
        if ("String".equals(javaType)) {
            return StringUtils.append("\"", value, "\"");
        }
        if ("Integer".equals(javaType)) {
            return StringUtils.append(value);
        }
        if ("Long".equals(javaType)) {
            return StringUtils.append(value, "L");
        }
        return null;
    }
}
